<?php

declare(strict_types=1);
/**
 * 后台管理员登录处理
 * Author: Zane
 * Email: 873934580@qq.com
 * Date: 2023/5/25.
 */

namespace App\Service;

use App\Enum\StatusEnum;
use App\Exceptions\CommonExceptionConstants;
use App\Exceptions\ServiceException;
use App\Models\System;
use App\Models\SystemLog;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Hash;

class LoginService
{
    /**
     * 登录处理.
     *
     * @param array $data
     *
     * @return array
     */
    public function login(array $data): array
    {
        $this->checkCode();
        $system = System::query()->where('username', $data['username'])->first();
        $this->attempt($data['username']);
        if (!$system || !Hash::check($data['password'], $system->password)) {
            $this->addAttempt($data['username']);
            $this->log($system);

            throw new ServiceException(CommonExceptionConstants::ACCOUNT_ERROR);
        }

        // 登录锁定验证
        if (StatusEnum::ENABLE !== $system->status) {
            $this->addAttempt($data['username']);
            $this->log($system);

            throw new ServiceException(CommonExceptionConstants::LIMIT_LOGIN);
        }

        $token = Auth::guard('system')->login($system);
        $system->login_ip = request()->getClientIp();
        $system->login_at = time();
        $system->save();
        $this->log($system, StatusEnum::ENABLE);

        return [
            'nickname' => $system->nickname,
            'username' => $system->username,
            'mobile' => $system->mobile,
            'avatar' => $system->avatar,
            'email' => $system->email,
            'login_at' => $system->login_at,
            'token' => $token,
        ];
    }

    /**
     * 校验登录尝试次数.
     *
     * @param mixed $username
     */
    private function attempt($username): void
    {
        //TODO 是否开启登录尝试限制 尝试限制多少,对设备的限制
        $num = Cache::get('login_'.$username);
        if ($num > 10) {
            throw new ServiceException(__('exception.login.attempt', ['seconds' => 10]));
        }
    }

    /**
     * 记录尝试错误次数.
     *
     * @param mixed $username
     */
    private function addAttempt($username): void
    {
        $key = 'login_'.$username;
        $num = Cache::get($key, 0);
        ++$num;
        Cache::put($key, $num, now()->addMinutes(10));
    }

    /**
     * 记录登录日志.
     *
     * @param $system
     * @param int $status
     */
    private function log($system, int $status = StatusEnum::DISABLE): void
    {
        if (!$system) {
            return;
        }
        $log = new SystemLog();
        $log->system_id = $system->id;
        $log->login_at = time();
        $log->login_ip = (int) ip2long(request()->getClientIp());
        $log->status = $status;
        $log->save();
    }

    /**
     * 校验验证码
     */
    private function checkCode(): void
    {
    }
}
